from fastapi import APIRouter

# -*- coding: UTF-8 -*-
from datetime import datetime, timedelta
import jwt
from fastapi import Depends, HTTPException # , status
from starlette import status
from fastapi.security import OAuth2PasswordBearer,OAuth2PasswordRequestForm
from pydantic import BaseModel

from backend.app.app.crud_sys.query import judge_username
from backend.app.app import rsa_private_key
from backend.app.app.api.utils.encryption import rsa_decrypt

SECRET_KEY = "09d25e094faa6ca2556c8fjdklf920jfdks2j0f563b93f7099f6f0f4caa6cf63b88e8d3e7"# 密钥"09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM = "HS256"     # 算法
ACCESS_TOKEN_EXPIRE_MINUTES = 30    # 访问令牌过期分钟
ACCESS_TOKEN_REFRESH = 10     #令牌大于此值就刷新

token_router = APIRouter(prefix="/token", tags=["令牌"])

# oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api_v1/token/ver_usertoken")

class Token(BaseModel):     # 令牌空壳
    access_token: str
    token_type: str

# 验证用户
def authenticate_user(username: str, password: str):
    #查询用户名
    re = judge_username(username)
    if re:
        user = re[0]
        bac_pwd = re[1]
        bac_pwd = rsa_decrypt(bac_pwd,rsa_private_key)
        password = rsa_decrypt(password,rsa_private_key)
        if bac_pwd == password :
            return user
        else:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Incorrect password",
                headers={"WWW-Authenticate": "Bearer"},
            )
    else:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username",
            headers={"WWW-Authenticate": "Bearer"},
        )

#将现在时间转换为jwt的exp时间格式
def turn_exp():
    c = {}
    c.update({"iat": datetime.utcnow()})
    a = jwt.encode(c, SECRET_KEY, algorithm=ALGORITHM)
    d = jwt.decode(a, SECRET_KEY, algorithms=[ALGORITHM])
    d = d.get("iat")
    return d

# 创建访问令牌
def create_access_token(*, data: dict, expires_delta: int,avai:bool,user_status:str):
    to_encode = data.copy()
    to_encode.update({"status":user_status})        #令牌 身份
    to_encode.update({"iat": datetime.utcnow()})        #令牌签发时间
    access_token_expires = timedelta(minutes=expires_delta)  # timedelta表示两个datetime对象之间的差异。（来自datetime包）
    expire = datetime.utcnow() + access_token_expires
    to_encode.update({"exp": expire})   # expire 令牌到期时间

    to_encode.update({"available":avai})     #available 令牌是否可用
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

# 获取当前拥有令牌的用户
async def get_token_user(token: str = Depends(OAuth2PasswordBearer)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        #验证令牌用户名，有效性，有效期
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        # 将令牌值改为False,写入数据库时用，现在没用
        if payload.get("available") == False:
            raise credentials_exception
        if username is None:
            raise credentials_exception
        start = payload.get("iat")
        end = turn_exp()
        if (end-start)/60 >= ACCESS_TOKEN_EXPIRE_MINUTES:
            raise credentials_exception
    except :
        raise credentials_exception
    user = judge_username(username)
    user = user[0]
    if user is None:
        raise credentials_exception
    print('获取当前用户user :', user)
    if (end - start)/60 > ACCESS_TOKEN_REFRESH:
        payload["available"] = False    #之前的令牌作废
        #创立新的令牌并返回
        access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
        access_token = create_access_token(data={"sub": user}, expires_delta=access_token_expires, avai=True,user_status="user")
        return {"access_token": access_token, "token_type": "bearer","user":user,"new":True}
    else:
        return {"user":user,"new":False}

class u_p(BaseModel):
    username:str
    password:str
@token_router.post("/ver_usertoken", response_model=Token,name="测试请求令牌")
#form_data: OAuth2PasswordRequestForm = Depends()       up:u_p
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
    # 1、验证用户
    user = authenticate_user(form_data.username, form_data.password)
    # 2、access_token_expires访问令牌过期
    # access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) # timedelta表示两个datetime对象之间的差异。（来自datetime包）

    # 3、create_access_token创建访问令牌
    access_token = create_access_token(data={"sub": user},expires_delta=30,avai=True,user_status="user")
    # 返回
    return {"access_token": access_token, "token_type": "bearer"}

@token_router.get("/users/me/", name= "测试")
async def read_users_me(all = Depends(get_token_user)):

    # 返回
    return all

@token_router.get("/users/me/items/")
async def read_own_items(current_user= Depends(get_token_user)):
    return [{"item_id": "Foo", "owner": current_user}]

